<?php declare(strict_types=1);

namespace App\Services\ElectronicSignature\Strategy;


use App\Models\Store;
use App\Models\StoreBank;
use App\Models\StorePayWay;
use App\Services\ElectronicSignature\Exception\ElSignException;
use App\Util\RequestUtil;
use App\Util\Rsa\Md5Util;
use App\Vo\ResultVo;
use Illuminate\Support\Facades\Log;
use function EasyWeChat\Kernel\Support\get_client_ip;

class EasypayElectronicSignatureHandler extends AbstractElectronicSignature
{

    protected $domain = "";
    protected $orgId = "";
    protected $merId = "";
    protected $channelId = "";
    protected $appKey = "";


    //电子协议URL
    const  COMMONURL = "/EasypayMPSystem/ContractServet";

    //下载
    const DOWNLOAD = "/EasypayMPSystem/DownloadContractServet.do";

    //获取密钥
    const SECRECT_KEY = "/EasypayMPSystem/SignServet";

    const VERSION = "1.0";

    //申请开户
    public function __construct()
    {
        $this->orgId = config("elec.yisheng.orgId");
        $this->merId = config("elec.yisheng.merId");
        $this->channelId = config("elec.yisheng.channelId");
        $this->domain = config("elec.yisheng.domain");
        $this->appKey = config("elec.yisheng.appKey");
    }


    public function getApi(): string
    {
        return "easypay";
    }

    /**
     * @return ResultVo
     */
    public function open(Store $store): ResultVo
    {
        $type = $this->getApplyType((string)$store->store_type);

        $validData = [
            "people" => $store->people,
            "head_sfz_no" => $store->head_sfz_no,
            "people_phone" => $store->people_phone,
            "store_name" => $store->store_name,
        ];
        $validator = \Illuminate\Support\Facades\Validator::make($validData, [
            "people" => ["required"],
            "head_sfz_no" => ["required"],
            "people_phone" => ["required"],
            "store_name" => ["required"],
        ], [], [
            "people" => "店铺持有人姓名",
            "head_sfz_no" => "身份证号",
            "people_phone" => "联系手机号",
            "store_name" => "店铺名称"
        ]);
        if ($validator->fails()) {
            throw  new \Exception($validator->errors()->first());
        }
        switch ($type) {
            case "person":
                $txCode = "3001";
                //{"head":{"txTime":"20230421165518"},"person":{"personName":"万碧玉","identNo":"51050219880203076X","mobilePhone":"19382430203","authenticationMode":"公安部数据联网核查"},"notSendPwd":"1"}
                $body = [
                    "head" => [
                        "txTime" => date("YmdHis", time()),//yyyyMMddHHmmss
                    ],
                    "person" => [
                        "personName" => $validData["people"],
                        "identNo" => $validData["head_sfz_no"], //系统会校验身份证格式，不能是未成年人
                        "mobilePhone" => $validData["people_phone"], //邮箱与手机号不能同时为空；电子协议系统会校验手机号格式
                        "authenticationMode" => "公安部数据联网核查" //客户平台与电子协议系统中，明确的认证方式，例如：线下人工审核；公安部数据联网核查；绑定银行卡实名认证；其他
                    ],
                    "notSendPwd" => "1"
                ];
                $signatoryName = $validData["people"];
                break;
            case "company":
                $txCode = "3002";
                /*{"head":{"txTime":"20190102235959"},"enterprise":{"enterpriseName":"某公司
","identTypeCode":"3","identNo":"110101111111117","mobilePhone":"18800008888","landlinePhone":"0108352
6655","authenticationMode":"公安部"},"enterpriseTransactor":{"transactorName":"王某","identTypeCode":"0","identNo":"110101200101010018","address":"北京"},"notSendPwd":1}*/
//                $identNo = $validData["store_license_no"] ?? "";
                $identNo = $store->store_license_no ?? "";
                $identTypeCode = "8";
                if (empty($identNo)) {
                    $identNo = $validData["head_sfz_no"];
                    $identTypeCode = "0";
                }
                $body = [
                    "head" => [
                        "txTime" => date("YmdHis", time()),//yyyyMMddHHmmss
                    ],
                    "enterprise" => [
                        "enterpriseName" => $validData["store_name"],//企业名称
                        "identTypeCode" => $identTypeCode, //0 身份证  证件类型
                        "identNo" => $identNo, //证件号
                        "mobilePhone" => $validData["people_phone"],//手机号  企业电子签章的负责人或者经办人的手机号；邮箱与手机号不能同时为空；系统会校验手机号格式
                        "landlinePhone" => $validData["people_phone"],//企业联系电话
                        "authenticationMode" => "公安部数据联网核查",//客户平台与系统协议中，明确的认证方式，例如：线下人工审核；公安部数据联网核查；绑定银行卡实名认证；其他（说明方式）
                    ],
                    "enterpriseTransactor" => [
                        "transactorName" => $validData["people"],//经办人名称
                        "identTypeCode" => "0",//
                        "identNo" => $validData["head_sfz_no"],//系统会校验身份证格式，不能是未成年人
                    ],
                    "notSendPwd" => "1"
                ];
                $signatoryName = $validData["store_name"];
                break;
        }
        $reqData = [
            "termId" => $this->orgId,//电子协议系统分配的终端号
            "tradeTrace" => uniqid((string)time()),//请求流水，唯一，不包括特殊字符
            "contractBody" => json_encode($body),//请求的报文内容 详细见说明
            "merId" => $this->merId,//电子协议系统分配的商户号
            "txCode" => $txCode,//请求类型
            "version" => self::VERSION,//
            "channelId" => $this->channelId//电子协议系统分配的机构号
        ];

        //签名计算
        $reqData["sign"] = Md5Util::getSign($reqData, $this->appKey);
        //发送请求
        Log::channel("elec")->info("电子签名开户请求", [
            "url" => $this->domain . self::COMMONURL,
            "req" => $reqData
        ]);
        $resultString = RequestUtil::curlPost($this->domain . self::COMMONURL, $reqData);
        /**
         * {
         * "contractBody": "{\"head\":{\"txTime\":\"20230421165518\",\"retCode\":\"60000000\",\"retMessage\":\"OK\"},\"person\":{\"userId\":\"D612D67576BA17C8E05312016B0AD508\",\"personName\":\"万碧玉\",\"identTypeCode\":\"0\",\"identNo\":\"51050219880203076X\",\"mobilePhone\":\"19382430203\",\"authenticationMode\":\"公安部数据联网核查\",\"anXinSignMobilePhone\":\"193****0203\",\"usedEmailLogin\":1,\"usedMobileLogin\":1,\"isOpenSM2\":0},\"notSendPwd\":1}",
         * "resultCode": "00",
         * "sign": "40803B2D14F075F65F8F3564AAB3073E"
         * }
         */
        $resultArray = json_decode($resultString, true);
        Log::channel("elec")->info("电子签名开户行响应", [
            "res" => $resultArray
        ]);
        //分析响应结果 统一输出
        if (empty($resultArray) || !isset($resultArray["resultCode"])) {
            throw new ElSignException("响应失败");
        } else if ($resultArray["resultCode"] == "00") {
            $code = "ok";

            /**
             * {"head":{"txTime":"20190102235959","locale":"zh_CN","retCode":"60000000","retMessage":"OK"},"person":
             * {"userId":"305A6C85D2605A10E050007F01006BEA","personName":"张某
            * ","identTypeCode":"0","identNo":"110101200101010010","mobilePhone":"18800008888","address":"北京
             * ","authenticationMode":"公安部
             * ","anXinSignEmail":"188****8888@cfca.com.cn","anXinSignMobilePhone":"188****8888"},"notSendPwd":1}

             * {"head":{"txTime":"20190102235959","locale":"zh_CN","retCode":"60000000","retMessage":"OK"},"enterprise":{"userId":"32EC6E2FC9803961E050007F0100394E","enterpriseName":"某公司
             * ","identTypeCode":"3","identNo":"110101111111117","mobilePhone":"18800008888","landlinePhone":"010835
             * 26655","authenticationMode":"公安部
             * ","anXinSignEmail":"188****8888@cfca.com.cn","anXinSignMobilePhone":"188****8888"},"enterpriseTransac
             * tor":{"transactorName":"王某","identTypeCode":"1","identNo":"110101200101010018","address":"北京
             */
            $responseContractBody = json_decode($resultArray["contractBody"], true);
            $userId = "";
            switch ($type) {
                case "person":
                    $userId = $responseContractBody["person"]["userId"] ?? "";
                    break;
                case "company":
                    $userId = $responseContractBody["enterprise"]["userId"] ?? "";
                    break;
            }
            $response = [
                "user_id" => $userId,
                "signatoryName" => $signatoryName,
                "body" => $body
            ];
            $msg = "success";
        } else if (in_array($resultArray["resultCode"], ["01", "03", "06", "25", "30", "31", "42", "96", "98", "A0", "94"])) {
            $code = "failed";
            $response = [
                "user_id" => "",
                "signatoryName" => "",
                "body" => $body
            ];
            $msg = $resultArray["resultMsg"] ?? "error";
        } else {
            throw new ElSignException("响应失败");
        }
        return ResultVo::code($code)::data($response)::msg($msg);
    }

    //发送短信
    //通过给用户发送验证码，以验证码授权方式签署合同。验证码有效时间为 10 分钟。
    public function sms(array $param): ResultVo
    {
        if (empty($param["userId"])) {
            throw new \Exception("userId 参数不存在");
        }
//        {"head":{"txTime":"20230529154741"},"proxySign":{"randomCode":"45","userId":"CFC5D50666BE219BE05311016B0A4D22"}}
        $contractBody = [
            "head" => [
                "txTime" => date("YmdHis", time())
            ],
            "proxySign" => [
                "randomCode" => (string)rand(10, 99),
                "userId" => $param["userId"] ?? "",
            ]
        ];

        $reqData = [
            "termId" => $this->orgId,//
            "tradeTrace" => uniqid((string)time()),
            "contractBody" => json_encode($contractBody),
            "merId" => $this->merId,
            "txCode" => "3101",
            "version" => self::VERSION,
            "channelId" => $this->channelId,
        ];
        $reqData["sign"] = Md5Util::getSign($reqData, $this->appKey);

        Log::channel("elec")->info("发送短信验证码", [
            "req" => $reqData,
            "url" => $this->domain . self::COMMONURL
        ]);
        $resultString = RequestUtil::curlPost($this->domain . self::COMMONURL, $reqData);

        $resultArray = json_decode($resultString, true);

        Log::channel("elec")->info("发送短信验证码", [
            "req" => $reqData,
            "res" => $resultArray
        ]);
        if (empty($resultArray) || !isset($resultArray["resultCode"])) {
            throw new ElSignException("响应失败");
        } else if ($resultArray["resultCode"] == "00") {
            $code = "ok";
            /**
             * {"head":{"txTime":"20190102235959","locale":"zh_CN","retCode":"60000000","retMessage":"OK"},"proxySign":{"userId":"39126292503E6231E050007F01005DB1","randomCode ":"10"}}
             */
            $responseContractBody = json_decode($resultArray["contractBody"], true);
            $response = [
                "randomCode" => $responseContractBody["proxySign"]["randomCode"] ?? ""
            ];
            $msg = "success";
        } else if (in_array($resultArray["resultCode"], ["01", "03", "06", "25", "30", "31", "42", "96", "98", "A0", "94"])) {
            $code = "failed";
            $response = [];
            $msg = $resultArray["resultMsg"] ?? "error";
        } else {
            throw new ElSignException("响应失败");
        }
        return ResultVo::code($code)::data($response)::msg($msg);
    }

    protected function setTextValueInfo(array $params): array
    {
        //获取合同数据
        $store_id = $params["store_id"];
        $store = Store::query()->where("store_id", $store_id)->first();
        //查询账号
        $bank = StoreBank::query()->where("store_id", $store_id)->first();
        if (empty($bank)) {
            throw new \Exception("请设置店铺银行卡收款信息");
        }
        //查询费率
        $storePayWaysAli = StorePayWay::query()->where("store_id", $store_id)->where([
            "company" => $params["company"],
            "ways_source" => "alipay"
        ])->first();
        $storePayWaysWx = StorePayWay::query()->where("store_id", $store_id)->where([
            "company" => $params["company"],
            "ways_source" => "weixin",
        ])->first();
        $storePayWaysUnion = StorePayWay::query()->where("store_id", $store_id)->where([
            "company" => $params["company"],
            "ways_source" => "unionpay"
        ])->first();
        return [
//province_name	varchar	255	0	0	0	0	0							utf8	utf8_general_ci	0	0	0	0	0	0	0
//city_name	varchar	255	0	0	0	0	0							utf8	utf8_general_ci	0	0	0	0	0	0	0
//area_name	varchar	255	0	0	0	0	0							utf8	utf8_general_ci	0	0	0	0	0	0	0
//store_address	varchar	255	0	-1	0	0	0			'无地址'				utf8	utf8_general_ci	0	0	0	0	0	0	0
            "merName" => $store->store_name,//商户名/注册名
            "merAddr" => $store->province_name . " " . $store->city_name . " " . $store->store_address,//商户地址/注册地址
            "merLegal" => $store->head_name,//法人
            "contractDateYear" => date("Y", time()),//合同日期 YYYY
            "contractDateMonth" => date("m", time()),//合同日期 MM
            "contractDateDay" => date("d", time()),//合同日期 dd
            "merCode" => $store->store_id,//内部商户号
            "bizName" => $store->people,//经营名称
            "businLic" => $store->store_license_no,//统一 社会信用代码
            "bizAddr" => $store->province_name . " " . $store->city_name . " " . $store->store_address,//经营地址
            "legalCode" => $store->head_sfz_no,//法人身份证号
            "legalPhone" => $store->people_phone,//法人电话
            "linkmanPhone" => $store->people_phone,//联系人电话
            "accName" => $bank->store_bank_name,//	账号名称
            "bankName" => $bank->bank_name,//开户行
            "account" => $bank->bank_sfz_no,//账号
            "businScope" => $store->category_name,//经营范围/经营内容
            "otherTermTypeName" => "",
            "termMaintain" => "",//终端维护方
            "termPossess" => "",//终端所有权
            "termNum" => "",//终端数量
            "codeNum" => "",//行业码数量
            "chargeTypeDebit" => !empty($storePayWaysUnion) ? $storePayWaysUnion->rate_a : 0.3,//卡支付借记卡
            "chargeTypeDebitMax" => !empty($storePayWaysUnion) ? $storePayWaysUnion->rate_f_top : 20,//卡支付借记卡封顶值
            "chargeTypeCredit" => !empty($storePayWaysUnion) ? $storePayWaysUnion->rate_a : 0.3,//卡支付贷记卡
            "chargeTypeUnionpayDebit" => !empty($storePayWaysUnion) ? $storePayWaysUnion->rate_a : 0.3,//银联二维码借记卡
            "chargeTypeUnionpayDebitMax" => !empty($storePayWaysUnion) ? $storePayWaysUnion->rate_f_top : 20,//银联二维码借记卡封顶值
            "chargeTypeUnionpayCredit" => !empty($storePayWaysUnion) ? $storePayWaysUnion->rate_a : 0.6,//银联二维码贷记卡
            "chargeTypeUnionpayDisDebit" => "",//银联营销借记卡
            "chargeTypeUnionpayDisDebitMax" => "",//银联营销借记卡封顶值
            "chargeTypeUnionpayDisCredit" => "",//银联营销贷记卡
            "chargeTypeWxpay" => empty($storePayWaysWx) ? 0.3 : $storePayWaysWx->rate,//微信
            "chargeTypeAlipay" => empty($storePayWaysAli) ? 0.3 : $storePayWaysAli->rate,//支付宝
            "contractDate" => date("Y-m-d H:i:s", time()),// 合同日期
            "d1SettlementRatio" => "",//D1结算按比例
            "d1SettlementFee" => "",//D1结算按笔
            "d0SettlementRatio" => "",//D0结算按比例
            "checkSettleT1" => "√",//选择框-T1结算
            "checkSettleD1" => "",//选择框-D1结算
            "checkSettleD1Ratio" => "",//选择框-D1结算按比例
            "checkSettleD1Fee" => "√",//选择框-D1结算按笔
            "checkSettleD0" => "√",//选择框-D0结算
            "checkRefundTermYes" => "√"
        ];
    }

    public function createContract(string $code, array $params = []): ResultVo
    {
        /**
         * {"head":{"txTime":"20190102235959"}
         * ,"note":{"checkCode":"123456","randomCode":"10"},"createContract":
         * {"templateId":"1","isSign":0,"signInfos":[{"userId":"6327987D3B854A3A9F4A198426084F02","authorizationTime":"20190214171200","location":"192.168.116.25","signLocation":"Signature1","projectCode":"002","i
         * sProxySign":1}]," textValueInfo ":{"text19":"孙一
         * ","text18":"10000","text15":"30000","text3":"16","text14":"叁萬元整","text4":"孙一
         * ","text17":"10000","text1":"2019","text16":"10000","text2":"3","text7":"壹萬","text8":"壹萬元整
         * ","text5":"222321199112050001","text6":"成都","text9":"10000","text10":"壹萬元整
         * ","text11":"10000","text21":"001","text12":"壹萬元整","text13":"10000","text20":"成都支行"}}}
         *
         */
        $contractBody = [
            "head" => [
                "txTime" => date("YmdHis", time())
            ],
            "note" => [
                "randomCode" => (string)rand(0, 99),
                "checkCode" => $code
            ],
            "createContract" => [
                "templateId" => config("elec.yisheng.templateId"),//易生默认模板
                "isSign" => "1",
                "textValueInfo" => $this->setTextValueInfo($params),//对接合同参数
                "signInfos" => [
                    [
                        "userId" => $params["user_id"] ?? "",
                        "authorizationTime" => date("YmdHis", time()),
                        "location" => get_client_ip(),
                        "signLocation" => "s1",
                        "projectCode" => md5(uniqid((string)time())),
                        "isProxySign" => "1"
                    ]
                ],
                "signLocation" => "s0"
            ]
        ];
        $reqData = [
            "termId" => $this->orgId,//
            "tradeTrace" => uniqid((string)time()),
            "contractBody" => json_encode($contractBody),
            "merId" => $this->merId,
            "txCode" => "3201",
            "version" => self::VERSION,
            "channelId" => $this->channelId,
        ];
        $reqData["sign"] = Md5Util::getSign($reqData, $this->appKey);

        $resultString = RequestUtil::curlPost($this->domain . self::COMMONURL, $reqData);

        $resultArray = json_decode($resultString, true);

        Log::channel("elec")->info("创建合同", [
            "req" => $reqData,
            "res" => $resultArray
        ]);
        if (empty($resultArray) || !isset($resultArray["resultCode"])) {
            throw new ElSignException("响应失败");
        } else if ($resultArray["resultCode"] == "00") {
            $code = "ok";
            /**
             * {"head":{"txTime":"20190102235959","locale":"zh_CN","retCode":"60000000","retMessage":"OK"},"contract
             * ":{"contractNo":"MM20190413000000001","contractTypeCode":"MM","contractName":"买卖合同
             * ","contractState":1,"createTime":"20190413160044","expiredDate":"20190513","signatories":[{"userName"
             * :"李四的公司
             * ","identTypeCode":"3","identNo":"3301110017039721","signmentState":1,"signTime":20190413160044}]}}
             *
             */
            $responseContractBody = json_decode($resultArray["contractBody"], true);
            $response = [
                "contractNo" => $responseContractBody["contract"]["contractNo"] ?? "",
                "contractTypeCode" => $responseContractBody["contract"]["contractNo"] ?? "",
                "contractName" => $responseContractBody["contract"]["contractName"] ?? "",
                "contractState" => $responseContractBody["contract"]["contractState"] ?? "",
                "createTime" => $responseContractBody["contract"]["createTime"] ?? "",
                "expiredDate" => $responseContractBody["contract"]["expiredDate"] ?? "",
                "signatories" => $responseContractBody["signatories"] ?? [],
            ];
            $msg = "success";
        } else if (in_array($resultArray["resultCode"], ["01", "03", "06", "25", "30", "31", "42", "96", "98", "A0", "94"])) {
            $code = "failed";
            $response = [];
            $msg = $resultArray["resultMsg"] ?? "error";
        } else {
            throw new ElSignException("响应失败");
        }
        return ResultVo::code($code)::data($response)::msg($msg);
    }

    public function agreeContract(array $params): ResultVo
    {
        /**
         * {"head":{"txTime":"20190102235959"},"signContract":{"contractNo":"ZL20190826000000123","signInfo":{"userId":"39126292503E6231E050007F01005DB1","authorizationTime":"20190801095509","location":"211.94.108.226","signLocation":"Signature2","projectCode":"003","imageData":"iVBORw0KGgoAAAANSUhEUgAAATkAAAB6CAMAAADzhNS1AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAANlBMVEUAAADmAADmAADmAADmAADmAADmAADmAADmAADmAADmAADmAADmAAD9ct2hSzZByQ0GuO0E3mlX7uG53QNyZDTFDW9DTgxxN5ZVIcmZy897s6jhy+BA+4CcCP24U2GjGXKL3DyFHi0noYDklpT8YEfJWKCFRlo4OWly/DKb3NyeWMjN8aQ9yteFIwcpwJatoqO0zbwoB5hTwskhg1PJmi25eXT4OAbPFhriWv5qAXf47kZ/EBAdmJwIFctOjO60bo2Koj8tTLFVWXjSEv/PkJhzCCjWQclZyx9clYousgVt2t+5mPQLFgDcUp+c25K5sAPJiaHk9LaCKb270/NbDbxzj6Elgl044Wr+jUdOLlVu4JAlyXzn7ofO4MxwCKomYOR2fFVpWG5Dx+Jb3Q1wq61zwHIXjBw+yYRK4xYhOLLhLeBcgn5p+Ov9SQJETvaZH/27NoJvE2ISOHxjBc6xqDL89X5eCSFXXeRKVs8CinWz3M68Ct5Ji7/2jkc8IicG2J7jGFZdTzQGvGq7y3slw18jkHMCx8uKcSUaunlBpba3lj+KiOQcwU2q131PcyNssCYj3WR1lX1bQtHIkf6GP3Q7V6kjzAJ0Aqq5wfEqEOPAWORm6+7dcw2yw04EcTQhXAkJgfIYGeIgm4EyqDS3D7xHbk7V6C1/qG42ikMW7HKQowrJFDBwVoIh/rC6Xv1agHULEeKgd+U7Wbf2R66f0gvI4JzZ9aAbOvbPEm6OzmXGe0IOLid20K9IqB+2UpeF65WZL5C7Zhet0vClaORO2bWRe3x9KCK5I3ZfxJZF/wahTX73UWzZC9+9VOfa8JpPf+VQdHKZvJfkQD5MjesNcn9DiRxUiRxUiRxUiRxUiRxUiRxUiRxUiRxUiRxUiRxUiRxUBrmk+8reHsBnlb09gM8qe3sAn1X29gA+q38tvNrsgRqulgAAAABJRU5ErkJggg=="}}}
         *
         */
        $contractBody = [
            "head" => [
                "txTime" => date("YmdHis", time())
            ],
            "signContract" => [
                "contractNo" => $params["contractNo"],
                "signInfo" => [
                    "userId" => $params["userId"],
                    "authorizationTime" => date("YmdHis", time()),
                    "location" => get_client_ip(),
                    "signLocation" => "s1;",
                    "projectCode" => md5(uniqid((string)time())),
                ]
            ],
        ];
        $reqData = [
            "termId" => $this->orgId,//
            "tradeTrace" => uniqid((string)time()),
            "contractBody" => json_encode($contractBody),
            "merId" => $this->merId,
            "txCode" => "3206",
            "version" => self::VERSION,
            "channelId" => $this->channelId,
        ];
        $reqData["sign"] = Md5Util::getSign($reqData, $this->appKey);
        $resultString = RequestUtil::curlPost($this->domain . self::COMMONURL, $reqData);

        $resultArray = json_decode($resultString, true);

        Log::channel("elec")->info("签署合同", [
            "req" => $reqData,
            "res" => $resultArray
        ]);
        if (empty($resultArray) || !isset($resultArray["resultCode"])) {
            throw new ElSignException("响应失败");
        } else if ($resultArray["resultCode"] == "00") {
            $code = "ok";
            /**
             * {"head":{"txTime":"20190102235959","locale":"zh_CN","retCode":"60000000","retMessage":"OK"},"signContract":{"contractNo":"ZL20190826000000123","signInfo":{"userId":"39126292503E6231E050007F01005DB1","authorizationTime":"20190801095509","location":"211.94.108.226","signLocation":"Signature2","projectCode":"003"}}}
             *
             */
            $responseContractBody = json_decode($resultArray["contractBody"], true);
            $response = [
                "contractNo" => $responseContractBody["signContract"]["contractNo"] ?? "",
                "signInfo" => $responseContractBody["signContract"]["signInfo"] ?? [],
            ];
            $msg = "success";
        } else if (in_array($resultArray["resultCode"], ["01", "03", "06", "25", "30", "31", "42", "96", "98", "A0", "94"])) {
            $code = "failed";
            $response = [];
            $msg = $resultArray["resultMsg"] ?? "error";
        } else {
            throw new ElSignException("响应失败");
        }
        return ResultVo::code($code)::data($response)::msg($msg);
    }

    public function queryContract(array $params): ResultVo
    {
        /**
         * {"head":{"txTime":"20190102235959"},"contract":{"contractNo":"QT20190101000000001"}}
         *
         */
        $contractBody = [
            "head" => [
                "txTime" => date("YmdHis", time())
            ],
            "contract" => [
                "contractNo" => $params["contractNo"],
            ],
        ];
        $reqData = [
            "termId" => $this->orgId,//
            "tradeTrace" => uniqid((string)time()),
            "contractBody" => json_encode($contractBody),
            "merId" => $this->merId,
            "txCode" => "3210",
            "version" => self::VERSION,
            "channelId" => $this->channelId,
        ];
        $reqData["sign"] = Md5Util::getSign($reqData, $this->appKey);

        $resultString = RequestUtil::curlPost($this->domain . self::COMMONURL, $reqData);

        $resultArray = json_decode($resultString, true);

        Log::channel("elec")->info("查询合同", [
            "req" => $reqData,
            "res" => $resultArray
        ]);
        if (empty($resultArray) || !isset($resultArray["resultCode"])) {
            throw new ElSignException("响应失败");
        } else if ($resultArray["resultCode"] == "00") {
            $code = "ok";
            /**
             * {"head":{"txTime":"20160102235959","locale":"zh_CN","retCode":"60000000","retMessage":"OK"},"contract":{"contractNo":"QT20160413000000001","contractTypeCode":"QT","contractName":"信息咨询及管理服务协议
            * （趸缴）（2 联）
             * ","contractState":1,"createTime":"20160413160220","expiredDate":"20160513","signatories":[{"userName"
            * :"xx 网络科技有限公司
            * ","identTypeCode":"3","identNo":"110000017039721","signmentState":1,"signTime":20160413160220},{"user
             * Name":"孙三的公司
             * ","identTypeCode":"3","identNo":"3301110017039721","signmentState":1,"signTime":20160413160220}]}}
             *
             */
            $responseContractBody = json_decode($resultArray["contractBody"], true);
            $response = [
                "contractNo" => $responseContractBody["contract"]["contractNo"] ?? "",
                "contractTypeCode" => $responseContractBody["contract"]["contractTypeCode"] ?? "",
                "contractTypeName" => $responseContractBody["contract"]["contractTypeCode"] ?? "",
                "contractName" => $responseContractBody["contract"]["contractName"] ?? "",
                "contractState" => $responseContractBody["contract"]["contractState"] ?? "",
                "createTime" => $responseContractBody["contract"]["createTime"] ?? "",
                "expiredDate" => $responseContractBody["contract"]["expiredDate"] ?? "",
                "signState" => $responseContractBody["contract"]["signatories"][0]["signmentState"] ?? 0,
                "signatories" => $responseContractBody["contract"]["signatories"] ?? [],
            ];
            $msg = "success";
        } else if (in_array($resultArray["resultCode"], ["01", "03", "06", "25", "30", "31", "42", "96", "98", "A0", "94"])) {
            $code = "failed";
            $response = [];
            $msg = $resultArray["resultMsg"] ?? "error";
        } else {
            throw new ElSignException("响应失败");
        }
        return ResultVo::code($code)::data($response)::msg($msg);
    }

    public function downloadContract(array $params): ResultVo
    {
        /**
         * {"head":{"txTime":"20190102235959"},"contract":{"contractNo":"QT20190101000000001"}}
         *
         */
        $reqData = [
            "termId" => $this->orgId,//
            "tradeTrace" => uniqid((string)time()),
            "contractNo" => $params["contractNo"],
            "merId" => $this->merId,
            "txCode" => "3210",
            "version" => self::VERSION,
            "channelId" => $this->channelId,
        ];
        $reqData["sign"] = Md5Util::getSign($reqData, $this->appKey);

        $resultString = RequestUtil::curlPost($this->domain . self::DOWNLOAD, $reqData);

        $resultArray = json_decode($resultString, true);

        Log::channel("elec")->info("下载合同", [
            "req" => $reqData,
            "res" => $resultArray
        ]);
        if (empty($resultArray) || !isset($resultArray["resultCode"])) {
            throw new ElSignException("响应失败");
        } else if ($resultArray["resultCode"] == "00") {
            $code = "ok";
            $response = [
                "pdfFileData" => $resultArray["pdfFileData"] ?? "",
            ];
            $msg = "success";
        } else if (in_array($resultArray["resultCode"], ["01", "03", "06", "25", "30", "31", "42", "96", "98", "A0", "94"])) {
            $code = "failed";
            $response = [];
            $msg = $resultArray["resultMsg"] ?? "error";
        } else {
            throw new ElSignException("响应失败");
        }
        return ResultVo::code($code)::data($response)::msg($msg);
    }

    public function getSecretKey()
    {
        //通过签名获取
        $reqData = [
            "channelId" => $this->channelId,
            "tradeTrace" => uniqid((string)time()),
            "version" => "3.0",
        ];
        $reqData["sign"] = Md5Util::getSign($reqData, config("elec.yisheng.master_appkey"));

        $resultString = RequestUtil::curlPost($this->domain . self::SECRECT_KEY, $reqData);

        $resultArray = json_decode($resultString, true);
        // TODO: Implement getSecretKey() method.
        Log::channel("elec")->info("获取签名", [
            "req" => $reqData,
            "res" => $resultArray
        ]);
        if (empty($resultArray) || !isset($resultArray["resultCode"])) {
            throw new ElSignException("响应失败");
        } else if ($resultArray["resultCode"] == "00") {
            $code = "ok";
            $response = [
                "key" => $resultArray["key"] ?? "",
            ];
            $msg = "success";
        } else if (in_array($resultArray["resultCode"], ["01", "03", "06", "25", "30", "31", "42", "96", "98", "A0", "94"])) {
            $code = "failed";
            $response = [];
            $msg = $resultArray["resultMsg"] ?? "error";
        } else {
            throw new ElSignException("响应失败");
        }
        return ResultVo::code($code)::data($response)::msg($msg);
    }
}